﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace homeworkhero
{
    public abstract class CollidableSprite
    {
        public enum CollidableSpriteType {
            PLAYER = 0,
            ENEMY = 1,
            BULLET = 2,
            PROP = 3
        }

        protected Stage stage;

        protected AnimationSet animSet;
        private Vector2 position;
        private Vector2 velocity;
        private Vector2 dimensions;
        private Vector2 origin;
        float rotation;
        private CollidableSpriteType type;
        protected int health;
        protected bool dead;
        private bool collide = true;

        public CollidableSprite(Stage s, CollidableSpriteType t, AnimationSet animSet) {
            this.stage = s;
            this.type = t;
            this.animSet = animSet;
            dimensions = animSet.getDimensions();
            origin = new Vector2(dimensions.X / 2.0f, dimensions.Y);
            rotation = 0.0f;

            dead = false;
        }

        public bool shouldCollide() {
            return collide;
        }

        public Stage getStage() {
            return stage;
        }

        public CollidableSpriteType getType() {
            return type;
        }

        public int getLayer() {
            return (int)Math.Floor(position.Y);
        }

        public BoundingBox getBounds()
        {
            Vector3 topleft = new Vector3(position.X - origin.X, position.Y-0.1f, 0);
            Vector3 bottomright = new Vector3(topleft.X + dimensions.X, position.Y+0.1f, 0);
            return new BoundingBox(topleft, bottomright);
        }

        public Vector2 getPosition() {
            return position;
        }

        public Vector2 getVelocity() {
            return velocity;
        }

        public void setPosition(Vector2 pos) {
            if (pos.Y >= 5.0f)
                throw new Exception("Y position >= 5.0f");

            this.position.X = pos.X;
            this.position.Y = pos.Y;
            position.Y = MathHelper.Clamp(position.Y, 0.0f, 4.99f);
        }

        public void setVelocity(Vector2 vel) {
            this.velocity.X = vel.X;
            this.velocity.Y = vel.Y;
        }
        public void destroy()
        {
            dead = true;
        }

        public void setVelocityX(float x) {
            this.velocity.X = x;
        }

        public void setVelocityY(float y) {
            this.velocity.Y = y;
        }

        public void move(float x, float y) {
            position.X += x;

            position.Y += y;
            position.Y = MathHelper.Clamp(position.Y, 0.0f, 4.99f);
        }

        public void addToVelocity(float x, float y) {
            velocity.X += x;
            velocity.Y += y;
        }

        public virtual void update(GameTime t) {
            position += velocity;
            position.Y = MathHelper.Clamp(position.Y, 0.0f, 4.99f);

            if (!isDead())
            {
                animSet.getCurrAnimation().progress(t);
                if(animSet.getCurrAnimation().isStopped()) {
                    this.dead = true;
                }
            }
        }

        public abstract Vector2 getScreenPosition();

        public void draw(SpriteBatch b) {
            if (isDead())
                return;

            b.Draw(animSet.getCurrAnimation().getTexture(), getScreenPosition(), null, Color.White, rotation, origin, 1.0f, SpriteEffects.None, position.Y/5.0f);
        }

        public void damage(int h) {
            if (isDying() || isDead())
                return;

            this.health -= h;

            if (health <= 0)
            {
                animSet.setAnimation("dying");
                collide = false;
            }
        }

        public int getHealth() {
            return this.health;
        }

        /*
        public void setHealth(int h) {
            this.health = h;
        }
         */

        public bool isDying() {
            return (this.health <= 0);
        }

        public bool isDead() {
            return dead;
        }

        public abstract int getDamage();

        public AnimationSet getAnimationSet()
        {
            return animSet;
        }
    }
}
